
package com.joysuch.wwyt.dataimport.patch.service.impl;

import java.util.Iterator;
import java.util.List;
import java.util.Optional;

import javax.transaction.Transactional;

import com.joysuch.wwyt.dataimport.patch.service.EvaluationRecordAddToRepoPatch;
import com.joysuch.wwyt.risk.entity.RiskEvaluationRepo;
import com.joysuch.wwyt.risk.entity.RiskPoint;
import com.joysuch.wwyt.risk.entity.RiskPointEvaluationJha;
import com.joysuch.wwyt.risk.entity.RiskPointEvaluationScl;
import com.joysuch.wwyt.risk.enums.EvaluationStates;
import com.joysuch.wwyt.risk.enums.EvaluationTypes;
import com.joysuch.wwyt.risk.repository.RiskPointDao;
import com.joysuch.wwyt.risk.repository.RiskPointEvaluationJhaDao;
import com.joysuch.wwyt.risk.repository.RiskPointEvaluationSclDao;
import com.joysuch.wwyt.risk.service.RiskEvaluationRepoService;
import com.joysuch.wwyt.risk.service.RiskPointService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class EvaluationRecordAddToRepoPatchImpl implements EvaluationRecordAddToRepoPatch {

    private static final Logger logger = LoggerFactory.getLogger(EvaluationRecordAddToRepoPatchImpl.class);

    @Autowired
    private RiskPointEvaluationJhaDao jhaDao;
    @Autowired
    private RiskPointEvaluationSclDao sclDao;
    @Autowired
    private RiskPointDao riskPointDao;
    @Autowired
    private RiskPointService riskPointService;
    @Autowired
    private RiskEvaluationRepoService riskEvaluationRepoService;

    @Override
    @Transactional
    public int patch() {
        // 暂存Context并重置。使sql对所有的数据都生效（所有tenentId及orgCode)
        // ShiroUser user = Context.getCurrentUser();
        // Context.setCurrentUser(null);
        List<RiskPointEvaluationJha> jhas = jhaDao.findAll();
        List<RiskPointEvaluationScl> scls = sclDao.findAll();
        logger.info("查询到{}条JHA评估, {}条SCL评估", jhas.size(), scls.size());
        // 删除已经在repo中存在的记录
        removeExitingRecords(jhas, scls);
        logger.info("移除重复后，还有{}条JHA评估, {}条SCL评估", jhas.size(), scls.size());
        // 保存jha记录
        saveJha(jhas);
        // 保存scl记录
        saveScl(scls);
        // 恢复threadlocal结果
        // Context.setCurrentUser(user);
        return jhas.size() + scls.size();
    }

    private void saveScl(List<RiskPointEvaluationScl> scls) {
        for (RiskPointEvaluationScl e : scls) {
            Optional<RiskPoint> point = riskPointDao.findById(e.getRiskPointId());
            if (!point.isPresent()) {
                // 风险点已经被删除
                continue;
            }
            RiskEvaluationRepo repo = riskEvaluationRepoService
                    .findMostImportantNotFromWorkSafetyCertByRiskPointIdAndType(e.getRiskPointId(),
                            EvaluationTypes.SCL);
            // logger.info("existing repo of type SCL found:" + repo);
            EvaluationStates state = EvaluationStates.EFFECTIVE;
            if (repo != null) {
                RiskPointEvaluationScl scl = sclDao.getOne(repo.getEvaluationId());
                // 存在有效记录，但是评估时间比当前早
                if (e.getCreateTime().after(scl.getCreateTime())) {
                    riskEvaluationRepoService.evaluationOutOfDate(repo.getId());
                } else {
                    state = EvaluationStates.OUT_OF_DATE;
                }
            }
            riskEvaluationRepoService.addRiskPointEvaluation(riskPointDao.getOne(e.getRiskPointId()),
                    riskPointDao.getOne(e.getRiskPointId()).getRiskDistrict().getId(),
                    EvaluationTypes.SCL, "LSR", e.getId(), EvaluationStates.EFFECTIVE, e.getRiskLevel());
            logger.info(e.toString());
            if (state == EvaluationStates.EFFECTIVE) {
                riskPointService.updateEvaluationStatus(e.getRiskPointId(), EvaluationTypes.SCL, e.getId());
            }
        }
    }

    private void saveJha(List<RiskPointEvaluationJha> jhas) {
        for (RiskPointEvaluationJha e : jhas) {
            Optional<RiskPoint> point = riskPointDao.findById(e.getRiskPointId());
            if (!point.isPresent()) {
                // 风险点已经被删除
                continue;
            }
            RiskEvaluationRepo repo = riskEvaluationRepoService
                    .findMostImportantNotFromWorkSafetyCertByRiskPointIdAndType(e.getRiskPointId(),
                            EvaluationTypes.JHA);
            // logger.info("existing repo of type JHA found:" + repo);
            EvaluationStates state = EvaluationStates.EFFECTIVE;
            if (repo != null) {
                RiskPointEvaluationJha jha = jhaDao.getOne(repo.getEvaluationId());
                // 存在有效记录，但是评估时间比当前早
                if (e.getCreateTime().after(jha.getCreateTime())) {
                    riskEvaluationRepoService.evaluationOutOfDate(repo.getId());
                } else {
                    state = EvaluationStates.OUT_OF_DATE;
                }
            }
            riskEvaluationRepoService.addRiskPointEvaluation(riskPointDao.getOne(e.getRiskPointId()),
                    riskPointDao.getOne(e.getRiskPointId()).getRiskDistrict().getId(),
                    EvaluationTypes.JHA, "LEC", e.getId(), state, e.getRiskLevel());
            if (state == EvaluationStates.EFFECTIVE) {
                riskPointService.updateEvaluationStatus(e.getRiskPointId(), EvaluationTypes.JHA, e.getId());
            }
        }
    }

    private void removeExitingRecords(List<RiskPointEvaluationJha> jhas, List<RiskPointEvaluationScl> scls) {
        List<Long> existingJhaIds = riskEvaluationRepoService.findAllEvaluationIdsOfType(EvaluationTypes.JHA);
        List<Long> existingSclIds = riskEvaluationRepoService.findAllEvaluationIdsOfType(EvaluationTypes.SCL);
        removeJhaEvaluationById(jhas, existingJhaIds);
        removeSclEvaluationById(scls, existingSclIds);
    }

    private void removeJhaEvaluationById(List<RiskPointEvaluationJha> jhas, List<Long> existingJhaIds) {
        Iterator<RiskPointEvaluationJha> it = jhas.iterator();
        while (it.hasNext()) {
            RiskPointEvaluationJha e = it.next();
            if (existingJhaIds.contains(e.getId())) {
                it.remove();
            }
        }
    }

    private void removeSclEvaluationById(List<RiskPointEvaluationScl> jhas, List<Long> existingSclIds) {
        Iterator<RiskPointEvaluationScl> it = jhas.iterator();
        while (it.hasNext()) {
            RiskPointEvaluationScl e = it.next();
            if (existingSclIds.contains(e.getId())) {
                it.remove();
            }
        }
    }

}
